package me.youline.dataServer.dao.impl;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import me.youline.dataServer.ConfigConstants;
import me.youline.dataServer.dao.UserTokenDAO;
import me.youline.dataServer.entity.UserToken;
import me.youline.dataServer.service.support.LogMsgBuilder;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.perf4j.aop.Profiled;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

@Component("userTokenCacheDAOImpl")
public class UserTokenCacheDAOImpl implements UserTokenDAO {

	private static Logger logger = LoggerFactory.getLogger(UserTokenCacheDAOImpl.class);
	
	private LoadingCache<String, UserToken> tokenCache = null;
	
	@Autowired
	private UserTokenLoadCommand command;
	
	@PostConstruct
	private void initialCache() {
		tokenCache = CacheBuilder.newBuilder()
				.refreshAfterWrite(30, TimeUnit.MINUTES).concurrencyLevel(1)
				.maximumSize(ConfigConstants.TOKEN_CACHE_NUMS).build(new CacheLoader<String, UserToken>() {
					@Override
					public UserToken load(String key) throws Exception {
						logger.debug(LogMsgBuilder.build().info().module("userTokenCacheService").interfaceName("cache-load-db-token").msg("cache load db tokenInfo "+key).getLogInfo());
						return command.load(key);
					}
				});
	}

	@Override
	@Profiled(tag="cache-存储token")
	public void save(UserToken token) {
		tokenCache.put(token.getToken(), token);
	}

	@Override
	@Profiled(tag="cache-删除token")
	public boolean deleteUserToken(String token) {
		tokenCache.invalidate(token);
		return true;
	}

	@Override
	@Profiled(tag="cache-更新token过期时间")
	public boolean updateExpiredAtTime(String token, Date time) {
		UserToken t = tokenCache.getIfPresent(token);
		tokenCache.invalidate(token);
		t.setExpiredAt(time.getTime());
		tokenCache.put(token, t);
		return true;
	}

	@Override
	@Profiled(tag="cache-根据token字符串获取token")
	public UserToken getUserTokenByTokenStr(String token) {
		try {
			return tokenCache.get(token);
		} catch (Exception e) {
			logger.debug(e.getMessage(),e);
			return null;
		}
	}

	protected LoadingCache<String, UserToken> getCache() {
		return this.tokenCache;
	}

	@Override
	@Profiled(tag="cache-删除过期token")
	public void deleteExpiredToken(Date date) {
		Collection<UserToken> collection = this.tokenCache.asMap().values();
		if(collection == null || collection.isEmpty()){
			return;
		}
		Set<String> set = new HashSet<String>(collection.size());
		for(UserToken t : collection){
			if(t.isExpired(date)){
				logger.info("[remove_token] user {} 's token that is expired  should be removed , at {} ",t.getUserName(),DateFormatUtils.format(t.getExpiredAt(), DateFormatUtils.ISO_DATETIME_FORMAT.getPattern()));
				set.add(t.getToken());
			}
		}
		this.getCache().invalidateAll(set);
	}

	@Override
	public UserToken getUserTokenByUserName(String userName) {
		throw new UnsupportedOperationException("当前缓存不支持对userName查询");
	}

	@Override
	public List<UserToken> loadAllUserToken() {
		throw new UnsupportedOperationException("当前缓存不支持从缓存中获取所有的userToken");
	}

	@Override
	public UserToken getUserTokenTokenByUserId(Long userId) {
		throw new UnsupportedOperationException("当前缓存不支持根据用户ID获取userToken");
	}
	
	

}
